﻿
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.IO.IsolatedStorage;
using System.Linq;
using System.Windows;
using GalaSoft.MvvmLight.Messaging;
using mal.WP7.GoogleAnalytics.Business.GoogleApi;
using System;

namespace mal.WP7.GoogleAnalytics.Business.Repository
{
    public class WebsiteRepository
    {
        #region Fields
        private const string AccountsKey = "AccountsKey";
        private const string AccountsCountKey = "count";

        private static WebsiteRepository instance;

        private List<IGoogleAnalyticsService> googleAnalyticsServices;
        private List<Account> accounts;
        private List<Website> websites;
        private bool isLoading = false;
        #endregion

        #region Construction / Destruction
        public WebsiteRepository()
        {
            this.googleAnalyticsServices = null;
        }
        #endregion

        #region enum, struct, class

        #endregion

        #region Properties
        public static WebsiteRepository Instance
        {
            get
            {
                if (instance == null)
                {
                    instance = new WebsiteRepository();
                }

                return instance;
            }
        }

        public List<Website> Websites
        {
            get
            {
                if (this.websites == null)
                {
                    this.LoadWebsitesAsync();
                }

                return this.websites;
            }
        }

        public ReadOnlyCollection<Account> Accounts
        {
            get
            {
                if (this.accounts == null)
                {
                    this.LoadAccounts();
                }               

                return new ReadOnlyCollection<Account>(this.accounts.OrderBy(a => a.Login).ToList());
            }
        }
        #endregion

        #region Methods
        public void TestAccount(Account account)
        {
            IGoogleAnalyticsService googleAnalyticsService;

#if MOKE
            googleAnalyticsService = new GoogleAnalyticsServiceMoke(account.Login, account.Password);
#else
                googleAnalyticsService = new GoogleAnalyticsService(account.Login, account.Password);
#endif

            googleAnalyticsService.LoginCompleted += new LoginCompletedEventHandler(this.OnTestLoginCompleted);
            googleAnalyticsService.LoginAsync();
        }

        public void SaveAccount(Account newAccount)
        {
            if (!this.Accounts.Contains(newAccount))
            {
                Account account = this.Accounts.FirstOrDefault(a => a.Login.ToUpperInvariant() == newAccount.Login.ToUpperInvariant());

                if (account == null)
                {
                    this.accounts.Add(newAccount);
                }
                else
                {
                    account.Password = newAccount.Password;
                }
            }

            IsolatedStorageSettings.ApplicationSettings[AccountsCountKey] = this.accounts.Count;

            IsolatedStorageSettings.ApplicationSettings[AccountsKey] = this.accounts;
            IsolatedStorageSettings.ApplicationSettings.Save();

            this.Reset();
        }

        public void RemoveAccount(Account account)
        {
            if (this.accounts != null)
            {
                this.accounts.Remove(account);
            }
            else
            {
                this.accounts = new List<Account>();
            }

            IsolatedStorageSettings.ApplicationSettings[AccountsCountKey] = this.accounts.Count;
            IsolatedStorageSettings.ApplicationSettings[AccountsKey] = this.accounts;
            IsolatedStorageSettings.ApplicationSettings.Save();

            this.Reset();
        }

        private void LoadWebsitesAsync()
        {
            if (!this.isLoading)
            {
                if (this.Accounts.Count > 0)
                {
                    if (this.googleAnalyticsServices.Count > 0)
                    {
                        this.isLoading = true;

                        foreach (IGoogleAnalyticsService googleAnalyticsService in this.googleAnalyticsServices)
                        {
                            googleAnalyticsService.LoginAsync();
                        }
                    }
                }
                else
                {
                    this.websites = new List<Website>();
                    Deployment.Current.Dispatcher.BeginInvoke(() =>
                    {
                        Messenger.Default.Send<WebsitesAvailableMessage>(new WebsitesAvailableMessage());
                    });
                }
            }
        }

        private void LoadAccounts()
        {
            this.accounts = new List<Account>();

            try
            {
                if (IsolatedStorageSettings.ApplicationSettings.Contains(AccountsKey))
                {
                    this.accounts = (List<Account>)IsolatedStorageSettings.ApplicationSettings[AccountsKey];
                }
                else
                {
                    this.accounts = new List<Account>();
                }

                if (this.googleAnalyticsServices != null)
                {
                    this.googleAnalyticsServices.Clear();
                }
                else
                {
                    this.googleAnalyticsServices = new List<IGoogleAnalyticsService>();
                }

                foreach (Account account in this.Accounts)
                {
                    IGoogleAnalyticsService googleAnalyticsService;

#if MOKE
                googleAnalyticsService = new GoogleAnalyticsServiceMoke(account.Login, account.Password);
#else
                    googleAnalyticsService = new GoogleAnalyticsService(account.Login, account.Password);
#endif
                    this.googleAnalyticsServices.Add(googleAnalyticsService);
                    googleAnalyticsService.LoginCompleted += new LoginCompletedEventHandler(this.OnLoginCompleted);
                }
            }
            catch (Exception e)
            {
                Console.Write(e.Message);
            }
        }

        private void Reset()
        {
            this.accounts = null;
            this.websites = null;
            this.isLoading = false;
        }

        #endregion

        #region Methods
        private void SendMessage(WebsitesAvailableMessage message)
        {
            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                Messenger.Default.Send<WebsitesAvailableMessage>(message);
            });
        }
        #endregion

        #region Events
        private void OnLoginCompleted(object sender, LoginCompletedEventArgs e)
        {
            IGoogleAnalyticsService googleAnalyticsService = (IGoogleAnalyticsService)sender;

            this.isLoading = false;

            foreach (IGoogleAnalyticsService item in this.googleAnalyticsServices)
            {
                if (item.IsLoading)
                {
                    this.isLoading = true;
                }
            }

            if (e.Error != null)
            {
                this.SendMessage(new WebsitesAvailableMessage(e.Error));
            }
            else
            {
                if (this.websites == null)
                {
                    this.websites = new List<Website>();
                }

                this.websites.AddRange(e.WebSites);

                this.websites = this.websites.OrderBy(w => w.Name).ToList();

                foreach (Website item in this.Websites)
                {
                    item.GoogleAnalyticsService = googleAnalyticsService;
                }

                this.SendMessage(new WebsitesAvailableMessage());
            }
        }

        private void OnTestLoginCompleted(object sender, LoginCompletedEventArgs e)
        {
            IGoogleAnalyticsService googleAnalyticsService = (IGoogleAnalyticsService)sender;
            TestLoginMessage message;

            if (e.Error != null)
            {
                message = new TestLoginMessage(false);
            }
            else
            {
                message = new TestLoginMessage(true);
            }

            Deployment.Current.Dispatcher.BeginInvoke(() =>
            {
                Messenger.Default.Send<TestLoginMessage>(message);
            });
        }
        #endregion
    }
}
